"""
RedFire框架 - 统一依赖注入模块

提供常用的FastAPI依赖注入函数，包括用户认证、权限检查等
"""

from typing import Optional, List, Annotated
from fastapi import Depends, HTTPException, status, Request
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
import jwt
from datetime import datetime

from .security import SecurityService, TokenData
from .exceptions import AuthenticationError, AuthorizationError

# HTTP Bearer 认证方案
security = HTTPBearer()


async def get_current_user_id(
    credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)],
    request: Request
) -> str:
    """
    获取当前用户ID的依赖函数
    
    Args:
        credentials: HTTP Bearer 认证凭据
        request: FastAPI请求对象
        
    Returns:
        str: 用户ID
        
    Raises:
        HTTPException: 认证失败时抛出401错误
    """
    try:
        # 从请求中获取安全服务（通过DI容器注入）
        security_service = getattr(request.app.state, 'security_service', None)
        if not security_service:
            # 如果没有注入安全服务，使用默认配置
            security_service = SecurityService({
                "jwt_secret_key": "default-secret-key",
                "jwt_algorithm": "HS256",
                "jwt_expire_minutes": 30
            })
        
        # 验证JWT令牌
        token_data = security_service.verify_token(credentials.credentials)
        if not token_data or not token_data.user_id:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="Invalid authentication credentials",
                headers={"WWW-Authenticate": "Bearer"},
            )
        
        return str(token_data.user_id)
        
    except jwt.ExpiredSignatureError:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Token has expired",
            headers={"WWW-Authenticate": "Bearer"},
        )
    except jwt.InvalidTokenError:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid token",
            headers={"WWW-Authenticate": "Bearer"},
        )
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Authentication failed",
            headers={"WWW-Authenticate": "Bearer"},
        )


async def get_current_user_token_data(
    credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)],
    request: Request
) -> TokenData:
    """
    获取当前用户完整令牌数据的依赖函数
    
    Args:
        credentials: HTTP Bearer 认证凭据
        request: FastAPI请求对象
        
    Returns:
        TokenData: 令牌数据对象
        
    Raises:
        HTTPException: 认证失败时抛出401错误
    """
    try:
        # 从请求中获取安全服务
        security_service = getattr(request.app.state, 'security_service', None)
        if not security_service:
            security_service = SecurityService({
                "jwt_secret_key": "default-secret-key",
                "jwt_algorithm": "HS256",
                "jwt_expire_minutes": 30
            })
        
        # 验证JWT令牌
        token_data = security_service.verify_token(credentials.credentials)
        if not token_data:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="Invalid authentication credentials",
                headers={"WWW-Authenticate": "Bearer"},
            )
        
        return token_data
        
    except jwt.ExpiredSignatureError:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Token has expired",
            headers={"WWW-Authenticate": "Bearer"},
        )
    except jwt.InvalidTokenError:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid token",
            headers={"WWW-Authenticate": "Bearer"},
        )
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Authentication failed",
            headers={"WWW-Authenticate": "Bearer"},
        )


def require_roles(*required_roles: str):
    """
    创建需要特定角色的依赖函数
    
    Args:
        *required_roles: 需要的角色列表
        
    Returns:
        依赖函数
    """
    async def check_roles(
        token_data: Annotated[TokenData, Depends(get_current_user_token_data)]
    ) -> TokenData:
        """检查用户是否具有所需角色"""
        user_roles = set(token_data.roles)
        required_roles_set = set(required_roles)
        
        if not required_roles_set.intersection(user_roles):
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail=f"Insufficient permissions. Required roles: {', '.join(required_roles)}"
            )
        
        return token_data
    
    return check_roles


def require_permissions(*required_permissions: str):
    """
    创建需要特定权限的依赖函数
    
    Args:
        *required_permissions: 需要的权限列表
        
    Returns:
        依赖函数
    """
    async def check_permissions(
        token_data: Annotated[TokenData, Depends(get_current_user_token_data)]
    ) -> TokenData:
        """检查用户是否具有所需权限"""
        user_permissions = set(token_data.scopes)
        required_permissions_set = set(required_permissions)
        
        if not required_permissions_set.issubset(user_permissions):
            missing_permissions = required_permissions_set - user_permissions
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail=f"Insufficient permissions. Missing: {', '.join(missing_permissions)}"
            )
        
        return token_data
    
    return check_permissions


# 常用的依赖别名
CurrentUserID = Depends(get_current_user_id)
CurrentUserTokenData = Depends(get_current_user_token_data)
AdminUser = Depends(require_roles("admin"))
SuperUser = Depends(require_roles("admin", "superuser"))


# 可选的用户认证（允许匿名访问）
async def get_optional_current_user_id(
    request: Request,
    credentials: Optional[HTTPAuthorizationCredentials] = Depends(HTTPBearer(auto_error=False))
) -> Optional[str]:
    """
    获取可选的当前用户ID（允许匿名访问）
    
    Args:
        request: FastAPI请求对象
        credentials: 可选的HTTP Bearer认证凭据
        
    Returns:
        Optional[str]: 用户ID，如果未认证则返回None
    """
    if not credentials:
        return None
    
    try:
        # 从请求中获取安全服务
        security_service = getattr(request.app.state, 'security_service', None)
        if not security_service:
            return None
        
        # 验证JWT令牌
        token_data = security_service.verify_token(credentials.credentials)
        if not token_data or not token_data.user_id:
            return None
        
        return str(token_data.user_id)
        
    except Exception:
        # 认证失败时返回None而不是抛出异常
        return None


OptionalCurrentUserID = Depends(get_optional_current_user_id)
